﻿namespace NetFx.SMIL.References
{
  using System;
  using System.Text;
  using System.Collections;
  using System.Collections.Generic;

  using System.Reflection;
  using System.Reflection.Emit;
  using System.Runtime.InteropServices;

  using System.Diagnostics;
  using System.Diagnostics.CodeAnalysis;
  using System.Diagnostics.SymbolStore;
  using System.Security;
  using System.Security.Permissions;

  using NetFx.MSIL;

  //TODO: 需要添加解析域（[mscorlib]：是一个程序集引用）。

  /// <summary>
  /// 反射对象的引用。
  /// </summary>
  /// <remarks>
  /// 引用是指对指定反射对象的引述。
  /// 通常只使用标识(Identifier)来
  /// 代表指定反射对象。当使用反射
  /// 对象的时候，需要将引用解析为
  /// 对应的反射对象（或者反射对象
  /// 的定义）才能进一步的使用。
  /// 为了引用可以重用，实现者可以
  /// 使用Hashtable对引用标识和
  /// 引用对象进行关联，或者将引用
  /// 标识，引用对象以及反射对象
  /// 进行关联。为了完全脱离反射，
  /// 引用对象本身并不记录它对应
  /// 的反射对象。
  /// </remarks>
  public abstract class ReflectRef:Reference, IDisposable
  {
    #region Statics
    /// <summary>
    /// 创建反射引用。
    /// </summary>
    /// <param name="name">名称（仅对source为Label和Variable有效）</param>
    /// <param name="source">源。</param>
    /// <returns>对应的反射引用。</returns>
    public static ReflectRef of(string name,object source)
    {
      if (source != null)
      {
        if (source is Assembly)
        {
          return AssemblyRef.of(source as Assembly);
        }
        else if (source is MemberInfo)
        {
          return MemberRef.of(source as MemberInfo);
        }
        else if (source is Label)
        {
          return LabelRef.of(name, (Label)source);
        }
        else if (source is Module)
        {
          return ModuleRef.of(source as Module);
        }
        else if (source is ParameterInfo)
        {
          return ParameterRef.of(source as ParameterInfo);
        }
        else if (source is LocalVariableInfo)
        {
          return VariableRef.of(name, source as LocalVariableInfo);
        }
        else if (source is QualifiedIdentifier)
        {
          return MemberRef.of(source as QualifiedIdentifier);
        }
      }
      return null;
    }
    #endregion
    #region Fields
    /// <summary>
    /// 反射对象的标识符（全名）。
    /// </summary>
    protected string identifier = string.Empty;
    #endregion
    #region Properties
    /// <summary>
    /// 获取反射对象的标识符。
    /// </summary>
    public virtual string Identifier
    {
      get
      {
        return this.identifier;
      }
    }
    /// <summary>
    /// 获取引用对象的类型。
    /// </summary>
    public virtual DefType ReflectionType
    {
      get
      {
        return DefType.Any;
      }
    }
    public virtual bool HasReflectInfo
    {
      get
      {
        return false;
      }
    }
    /// <summary>
    /// 判别当前对象是否已经被处置。
    /// </summary>
    public virtual bool IsDisposed
    {
      get
      {
        return this.referenced == null;
      }
    }
    #endregion
    #region Constructors
    public ReflectRef():base()
    {
    }
    public ReflectRef(string identifier):this(identifier,null)
    {
    }
    public ReflectRef(string identifier,object source):this()
    {
      this.identifier = identifier == null ? string.Empty : identifier;
      this.OnBinding(source);
    }
    ~ReflectRef()
    {
      this.Dispose();
    }
    #endregion
    #region Methods
    /// <summary>
    /// 将引用绑定到指定的源。
    /// </summary>
    /// <param name="source">指定的源。</param>
    /// <returns>当前引用。</returns>
    /// <remarks>
    /// 派生类应负责判断source的类型，保证类型
    /// 能够符合合适的引用。
    /// 应使用 source as TYPE的形式调用base的
    /// OnBinding方法。如果source不符合TYPE的要求，
    /// 那么基类应调用OnSourceMissing方法。
    /// 派生类可以重写OnSourceMissing方法并掷出异常。
    /// 另一种方式是由派生类直接判别输入类型是否
    /// 合适并做出适当的处理。
    /// </remarks>
    public virtual ReflectRef Bind(object source)
    {
      return this.OnBinding(source);
    }
    /// <summary>
    /// 断开引用。
    /// </summary>
    /// <returns>当前引用。</returns>
    public virtual ReflectRef Break()
    {
      return this.OnBreaking(this.referenced);
    }
    /// <summary>
    /// 处置当前对象。
    /// </summary>
    public virtual void Dispose()
    {
      this.Dispose(!this.IsDisposed);
    }

    protected virtual void Dispose(bool disposing)
    {
      if (disposing)
      {
        this.Break();
        this.identifier = null;
        this.referenced = null;
      }
    }


    protected virtual ReflectRef OnBinding(object source)
    {
      if (source == null)
        this.OnSourceMissing();
      else
        this.referenced = source;
      return this;
    }
    protected virtual ReflectRef OnBreaking(object referenced)
    {
      this.referenced = null;
      return this;
    }
    protected virtual void OnSourceMissing()
    {

    }

    public override bool Equals(object obj)
    {
      if (obj is ReflectRef)
      {
        return this.ToString().Equals(obj.ToString());
      }
      return base.Equals(obj);
    }
    public override int GetHashCode()
    {
      return base.GetHashCode();
    }
    #endregion
  }
}
